package ru.spb.osll.myfit.server.comparing;

import ru.spb.osll.myfit.common.ComparisonResult;
import ru.spb.osll.myfit.common.Range;
import ru.spb.osll.myfit.common.chart.ChartCurve;
import ru.spb.osll.myfit.common.chart.ChartData;
import ru.spb.osll.myfit.common.chart.ChartPoint;
import ru.spb.osll.myfit.server.chart.ChartHandler;

import java.util.ArrayList;
import java.util.List;

public class Ratio implements ChartComparator {
  private ChartHandler m_chartHandler = new ChartHandler();

  public Ratio(ChartHandler chartHandler) {
    m_chartHandler = chartHandler;
  }

  @Override
  public String id() {
    return "Ratio";
  }

  @Override
  public ComparisonResult compare(List<String> ids, Range range) {
    ComparisonResult comparisonResult = new ComparisonResult();

    List<ChartData> ChartDataList = m_chartHandler.getChartDataList(ids);

    ChartCurve curve1 = ChartDataList.get(0).getCurves().get(0);
    ChartCurve curve2 = ChartDataList.get(1).getCurves().get(0);

    int first = findLastLesserIndex(curve1.getPoints(), range.getStart());
    int last = findFirstBiggerIndex(curve1.getPoints(), range.getStart() + range.getLength());

    double first1Value = getIntermediateValue(range.getStart(), curve1, first);
    double first2Value = getIntermediateValue(range.getStart(), curve2, first);

    double last1Value = getIntermediateValue(range.getStart() + range.getLength(), curve1, last);
    double last2Value = getIntermediateValue(range.getStart() + range.getLength(), curve2, last);

    ChartCurve newCurve = new ChartCurve();

    newCurve.getPoints().add(new ChartPoint(range.getStart(), first2Value/first1Value));
    for (int i = first + 1; i < last - 1; ++i) {
      newCurve.getPoints().add(new ChartPoint(curve1.getPoints().get(i).getX(), curve2.getPoints().get(i).getY()/curve1.getPoints().get(i).getY()));
    }
    newCurve.getPoints().add(new ChartPoint(range.getStart() + range.getLength(), last2Value/last1Value));
    List<ChartCurve> chartCurveList = new ArrayList<ChartCurve>();
    chartCurveList.add(newCurve);
//    comparisonResult.setCurves(chartCurveList);
    comparisonResult.setChartData(new ChartData(chartCurveList, "Ratio", "Time", "Value", "Ratio"));

    return comparisonResult;
  }

  private double getSquare(double x, double y, double xValue, double yValue) {
    return (xValue + yValue) / 2 * (y - x);
  }

  private double getIntermediateValue(double x, ChartCurve curve, int first) {
    return curve.getPoints().get(first).getY() +
            (curve.getPoints().get(first + 1).getY() - curve.getPoints().get(first).getY()) /
                    (curve.getPoints().get(first + 1).getX() - curve.getPoints().get(first).getX())
                    * (x - curve.getPoints().get(first).getX()) /
                    (curve.getPoints().get(first + 1).getX() - curve.getPoints().get(first).getX());
  }

  private int findFirstBiggerIndex(List<ChartPoint> points, double end) {
    int step = (int) (points.get(5).getX() - points.get(4).getX() + 0.5);
    int x = (int) (end / step - 1.5);
    if (x < 0) {
      x = 0;
    }
    for (int i = x; i < points.size(); ++i) {
      if (points.get(i).getX() > end)
        return i;
    }
    return points.size() - 2;
  }

  private int findLastLesserIndex(List<ChartPoint> points, double start) {
    int step = (int) (points.get(5).getX() - points.get(4).getX() + 0.5);
    int x = (int) (start / step - 1.5);
    if (x < 0) {
      x = 0;
    }
    for (int i = x; i < points.size(); ++i) {
      if (points.get(i).getX() > start)
        return i - 1;
    }
    return 0;
  }
}
